package com.bosssoft.cloud.wechat.common.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.bosssoft.cloud.check.service.CheckDownloadInvoiceService;
import com.bosssoft.cloud.check.vo.ElectronicInvoice;
import com.bosssoft.cloud.consts.InvoiceFileType;
import com.bosssoft.cloud.wechat.common.bean.einvoice.CkParam;
import com.bosssoft.cloud.wechat.common.bean.einvoice.EinvoiceDTO;
import com.bosssoft.cloud.wechat.common.bean.einvoice.EinvoiceVO;
import com.bosssoft.cloud.wechat.common.infra.properties.EipsManager;
import com.bosssoft.cloud.wechat.infrastructure.constant.EipsConfigConsts;
import com.bosssoft.cloud.wechat.common.service.AppCheckCountService;
import com.bosssoft.cloud.wechat.common.service.AppCheckRecordService;
import com.bosssoft.cloud.wechat.common.service.EInvoiceService;
import com.bosssoft.cloud.wechat.infrastructure.enums.ErrEnum;
import com.bosssoft.cloud.wechat.infrastructure.exception.BusinessException;
import com.bosssoft.cloud.wechat.infrastructure.util.Assert;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 财票查验相关服务*
 *
 * @author wcy create on 2021/5/14 16:09 下午
 */
@Slf4j
@Service
public class EInvoiceServiceImpl implements EInvoiceService {


    //   提供者加@Service可直接用@Reference省去dubbo.xml接口配置
    @Resource
    private CheckDownloadInvoiceService checkDownloadInvoiceService;
    @Autowired
    private AppCheckRecordService acrService;
    @Autowired
    private AppCheckCountService accService;

    @Resource
    private EipsManager eipsManager;

    /**
     * 通过交款人名称等信息查验票据
     * <p>
     * billCode     电子票据代码
     * billNumber   电子票据号码
     * randomNumber 校验码
     * payerName    交款人
     * type         查验类型 0_手工查验；1_扫码查验
     *
     * @return 电子票据
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public EinvoiceVO check(CkParam param) {
        // 非本地票据校验
        Assert.isTrue(param.getEInvoiceCode().startsWith(eipsManager.getLocalAreaCode()), ErrEnum.A0403, "非本地票据校验");
        // 获取票据信息
        ElectronicInvoice electronicInvoice = checkDownloadInvoiceService.downloadEInvoiceSingle(
                param.getEInvoiceCode(), param.getEInvoiceNumber(), param.getRandomNumber(), InvoiceFileType.PNG);
        // 非扫码查验要走交款人校验
        if (!(EipsConfigConsts.CHECK_BY_QRCODE.equals(param.getQrType()) ||
                electronicInvoice.getPayerPartyName().equalsIgnoreCase(param.getPayerPartyName()))) {
            log.error("输入交款人:" + param.getPayerPartyName() + ",实际：" + electronicInvoice.getPayerPartyName());
            throw new BusinessException(ErrEnum.A0403, "交款人名称错误");
        }
        EinvoiceDTO dto = BeanUtil.toBean(param, EinvoiceDTO.class);
        BeanUtil.copyProperties(
                electronicInvoice, dto, CopyOptions.create().setFieldMapping(
                        MapUtil.of(
                                EinvoiceDTO.CONST_PNG_BASE64_ELECTRONIC,
                                EinvoiceDTO.CONST_PNG_BASE64)
                ));
        // userId不为空时，记录本次用户查验票据信息记录
        if (StrUtil.isNotBlank(param.getUserId())) {
            // 用户类型默认为微信用户（ps：目前也只有微信）
            if (dto.getUserType() == null) dto.setUserType(EipsConfigConsts.USERTYPE_WX);
            log.info("本次查验做记录：{}", dto.toStringSimple());
            // 保存查验的票据信息记录
            acrService.save(dto);
            // 保存查验记录
            accService.save(dto);
        }
        return BeanUtil.toBean(dto, EinvoiceVO.class);
    }

    @Override
    public EinvoiceVO getInfoFromQrcode(String qrcodeinfo) {
        boolean flag = true;
        String eInvoiceNumber = null;
        String eInvoiceCode = null;
        String randomNum = null;
        // 目前只碰到处理CZ-EI开头的票据
        // 建议对可扫码票据的类型全面了解前，不要改造
        if (qrcodeinfo.startsWith("CZ-EI")) {
            try {
                String[] splits;
                if (qrcodeinfo.contains("http")) {
                    splits = qrcodeinfo.split("/");
                    splits = splits[splits.length - 1].split("\\.");
                    eInvoiceCode = splits[1].trim();
                    eInvoiceNumber = splits[2].trim();
                    randomNum = splits[3].trim();
                } else if (qrcodeinfo.indexOf(",") > 0) {
                    splits = qrcodeinfo.split(",");
                    eInvoiceCode = splits[2].trim();
                    eInvoiceNumber = splits[3].trim();
                    randomNum = splits[4].trim();
                } else if (qrcodeinfo.indexOf("；") > 0) {
                    splits = qrcodeinfo.split("；");
                    eInvoiceCode = splits[2].split(":")[1].trim();
                    eInvoiceNumber = splits[1].split(":")[1].trim();
                    randomNum = splits[3].split(":")[1].trim();
                } else if (qrcodeinfo.indexOf(";") > 0) {
                    splits = qrcodeinfo.split(";");
                    eInvoiceCode = splits[2].split(":")[1].trim();
                    eInvoiceNumber = splits[1].split(":")[1].trim();
                    randomNum = splits[3].split(":")[1].trim();
                } else {
                    flag = false;
                }
            } catch (Exception e) {
                flag = false;
                log.warn("解析二维码失败：{}", e.getMessage());
            }
        } else if (qrcodeinfo.startsWith("开票时间")) {
            try {
                String[] splits = qrcodeinfo.split("；");
                eInvoiceCode = splits[2].trim().split(":")[1].trim();
                eInvoiceNumber = splits[1].trim().split(":")[1].trim();
                randomNum = splits[3].trim().split(":")[1].trim();
            } catch (Exception e) {
                flag = false;
                log.warn("解析二维码失败：{}", e.getMessage());
            }
        } else {
            flag = false;
        }
        // 解析失败
        Assert.isTrue(flag, ErrEnum.A0434, qrcodeinfo);
        EinvoiceVO invoice = new EinvoiceVO();
        invoice.setEInvoiceCode(eInvoiceCode);
        invoice.setEInvoiceNumber(eInvoiceNumber);
        invoice.setRandomNumber(randomNum);
        return invoice;
    }
}
